package com.hiutil.cbo;

import java.lang.reflect.Method;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;

public class HiCBO {
    /**
     * 根据回调填充对象
     * @param obj
     * @param type
     * @param handler
     * @return
     */
	public static <T> boolean fillObject(T obj, Class<T> type, Function<String, String> handler)  {
    	return fillObject(obj, type, (key, cls)->{
    		return handler.apply(key);
    	});
    }

    /**
     * 根据回调填充对象
     * @param obj
     * @param type
     * @param handler
     * @return
     */
    public static <T> boolean fillObjectEx(T obj, Class<T> type, Function<String, Object> handler)   {
    	return fillObject(obj, type, (key, cls)->{
    		return handler.apply(key);
    	});
    }

    public static <T> void readObject(T obj, Class<T> type, BiConsumer<String, Object> handler) {
    	if (null == obj || null == type || null == handler) {
    		return;
    	}

    	Method[] methods = type.getMethods();

    	for (int i = 0; i < methods.length; i++) {
    		Method method = methods[i];
    		String name = method.getName();
    		if (!name.startsWith("get")) {
    			continue;
    		}

    		if (method.getParameters().length != 1) {
    			continue;
    		}

    		Class<?> cls = method.getParameterTypes()[0];
    		if (cls == null) {
    			continue;
    		}
    		String property = name.substring(3, name.length());

    		try {
				Object val = method.invoke(obj);
				handler.accept(property, val);
    		} catch(Exception ex) {
    			ex.printStackTrace();
    		}
    	}
    }

    /**
     * 根据提供数据装载对象
     * @param obj
     * @param type
     * @param handler
     * @return
     */
    private static <T> boolean fillObject(T obj, Class<T> type, BiFunction<String, Class<?>, Object> handler)   {
    	if (obj == null || handler == null) {
    		return false;
    	}

    	Method[] methods = type.getMethods();

    	for (int i = 0; i < methods.length; i++) {
    		Method method = methods[i];
    		String name = method.getName();
    		if (!name.startsWith("set")) {
    			continue;
    		}

    		if (method.getParameters().length != 1) {
    			continue;
    		}

    		Class<?> cls = method.getParameterTypes()[0];
    		if (cls == null) {
    			continue;
    		}
    		String property = name.substring(3, name.length());

    		try {
        		Object value = handler.apply(property, cls);
    			Object ret =  HiTypeHelper.Cast(cls, value);
				method.invoke(obj, ret);
    		} catch(Exception ex) {
    			ex.printStackTrace();
    		}
    	}
        return true;
    }
}
